import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Map {

	private static long lastId = 0;
	
	private List<Agent> agents;

	private List<Tree> trees;
	
	private List<Machine> machines;
	
	private List<PowerPlant> powerPlants;

	public List<PowerPlant> getPowerPlants() {
		return powerPlants;
	}
	
	public void setPowerPlants(List<PowerPlant> powerPlants) {
		this.powerPlants = powerPlants;
	}

	private MapParameters parameters;

	private MapObject[][] map;

	public Map() {
		agents = new LinkedList<Agent>();
		trees = new LinkedList<Tree>();
		machines = new LinkedList<Machine>();
		powerPlants = new LinkedList<PowerPlant>();
		setParameters(new MapParameters());
		initMap();
		initHumans();
		initMachines();
		initTrees();
		initPowerplants();
		initZombies();
	}

	@SuppressWarnings("incomplete-switch")
	public void printMap() {
		for (int x = 0; x < getMap().length; x++) {
			for (int y = 0; y < getMap()[0].length; y++) {
				MapObject wo = getMap()[x][y];
				String symbol = "";
				switch (wo.getType()) {
				case EMPTY_SPACE:
					symbol = "_";
					break;
				case Human:
					symbol = "H";
					break;
				case Zombie:
					symbol = "Z";
					break;
				case Tree:
					symbol = "T";
					break;
				case PowerPlant:
					symbol = "P";
					break;
				case Machine:
					symbol = "M";
					break;
				}
				System.out.print(symbol);
			}
			System.out.println("");
		}
	}

	public void weaken()
	{
		for(Agent a : agents)
		{
			a.setEnergy(a.getEnergy()-1);
		}
	}
	
	private void initMap() {
		setMap(new MapObject[getParameters().getMAP_HEIGHT()][getParameters()
				.getMAP_WIDTH()]);
		for (int x = 0; x < getParameters().getMAP_HEIGHT(); x++) {
			for (int y = 0; y < getParameters().getMAP_WIDTH(); y++) {
				getMap()[x][y] = new BlankSpace(new Point(x, y));
				getMap()[x][y].setId(-1);
			}
		}
	}

	private void initHumans() {
		ArrayList<Human> humans = new ArrayList<Human>();
		Point p;
		
		
		
		for (int i = 0; i < getParameters().getINIT_BACTERIA_POPULATION(); i++) {
			Point randPos = new Point((int) (Math.random()
					* getParameters().getMAP_WIDTH()), (int) (Math.random()
					* getParameters().getMAP_HEIGHT()));
			p = MapUtils.getSpaceToPut(getMap(), randPos);
			
			Human human = new Human(p);
			human.setId(Map.lastId++);
			getMap()[human.getPosition().y][human.getPosition().x] = human;
			humans.add(human);
		}
		agents.addAll(humans);
	}
	
	private void initMachines() {
		ArrayList<Machine> machines = new ArrayList<Machine>();
		Point p;
	
		Point randPos = new Point((int) (Math.random()
				* getParameters().getMAP_WIDTH()), (int) (Math.random()
				* getParameters().getMAP_HEIGHT()));
		p = MapUtils.getSpaceToPut(getMap(), randPos);
		
		Machine machine = new Machine(p);
		machine.setId(Map.lastId++);
		getMap()[machine.getPosition().y][machine.getPosition().x] = machine;
		machines.add(machine);
		
		agents.addAll(machines);
	}
	
	private void initZombies() {
		ArrayList<Zombie> zombies = new ArrayList<Zombie>();
		Point p;
		for (int i = 0; i < 5; i++) {
			Point randPos = new Point((int) (Math.random()
					* getParameters().getMAP_WIDTH()), (int) (Math.random()
					* getParameters().getMAP_HEIGHT()));
			p = MapUtils.getSpaceToPut(getMap(), randPos);
			Zombie zombie = new Zombie(p);
			zombie.setId(this.lastId++);
			getMap()[zombie.getPosition().y][zombie.getPosition().x] = zombie;
			zombies.add(zombie);
		}
		agents.addAll(zombies);
	}

	private void initTrees() {
		for(int i = 0; i < 2; i++) {
		Point randPoint1 = new Point((int) (Math.random()
				* getParameters().getMAP_WIDTH()), (int) (Math.random()
				* getParameters().getMAP_HEIGHT()));

		Point p = MapUtils.getSpaceToPut(getMap(), randPoint1);
		
		Tree tree = new Tree(p);
		tree.setId(this.lastId++);
		trees.add(tree);
		
		getMap()[tree.getPosition().y][tree.getPosition().x] = tree;
		}
	}
	
	private void initPowerplants() {
		for(int i = 0; i < 2; i++) {
		Point randPoint1 = new Point((int) (Math.random()
				* getParameters().getMAP_WIDTH()), (int) (Math.random()
				* getParameters().getMAP_HEIGHT()));

		Point p = MapUtils.getSpaceToPut(getMap(), randPoint1);
		
		PowerPlant powerPla = new PowerPlant(p);
		powerPla.setId(this.lastId++);
		powerPlants.add(powerPla);
		
		getMap()[powerPla.getPosition().y][powerPla.getPosition().x] = powerPla;
		}
	}

	public List<Agent> getAgents() {
		return this.agents;
	}
	
	public LinkedList<Zombie> getZombies()
	{
		LinkedList<Zombie> zombies = new LinkedList<Zombie>();
		for(Agent a : agents )
		{
			if(a instanceof Zombie )
			{
				zombies.add((Zombie) a);
			}
		}
		
		return zombies;
	}
	
	public LinkedList<Human> getHumans()
	{
		LinkedList<Human> humans = new LinkedList<Human>();
		for(Agent a : agents )
		{
			if(a instanceof Human )
			{
				humans.add((Human) a);
			}
		}
		
		return humans;
	}
	
	public LinkedList<Machine> getMachines()
	{
		LinkedList<Machine> machines = new LinkedList<Machine>();
		for(Agent a : agents )
		{
			if(a instanceof Machine )
			{
				machines.add((Machine) a);
			}
		}
		
		return machines;
	}
	
	public MapObject getObjectOfId(long id)
	{
		for(MapObject[] objects : map)
		{
			for(MapObject object : objects)
			{
				if(object.getId() == id)
					return object;
			}
		}
		return null;
	}
	
	public MapParameters getParameters() {
		return parameters;
	}

	public void setParameters(MapParameters parameters) {
		this.parameters = parameters;
	}

	public MapObject[][] getMap() {
		return map;
	}

	public void setMap(MapObject[][] map) {
		this.map = map;
	}

	List<Tree> getTrees() {
		return trees;
	}

	public void setTrees(List<Tree> trees) {
		this.trees = trees;
	}
	
	public void setAgents(LinkedList<Agent> agents) {
		this.agents = agents;
	}

}
